﻿using System;
using System.IO;
using UnityEditor;
using UnityEngine;
using System.Collections.Generic;
using System.Collections;

namespace hxweditor
{

	public enum AssetBundleBuildType
	{
		ui,
		effect,
		actor,
        scene,
	}

	public class AssetBundleTool
	{

		/// <summary>
		/// 创建assetbundle
		/// </summary>
		/// <param name="targetPath">打包目录</param>
		/// <param name="outPath">输出目录</param>
		/// <param name="buildtarget">平台类型</param>
		/// <param name="buildOptions">编译选项</param>
		/// <param name="type">资源类型</param>
		/// <param name="isFile">true以文件为单位，false以目录为单位</param>
		public static void CreatAssetBundle (string targetPath, string outPath, BuildTarget buildtarget, BuildAssetBundleOptions buildOptions, AssetBundleBuildType type,string mainName = "")
		{
			//根据参数，获得需要打包的列表
			List<AssetBundleBuild> BuildList = null;
            switch(type){
                case AssetBundleBuildType.scene:
                    BuildList = SceneAssetBundleTool.GetSceneAssetBundleBuild(targetPath);
                    break;
                case AssetBundleBuildType.actor:
                case AssetBundleBuildType.effect:
                    BuildList = RootDirByFile(targetPath, getFilter(type));
                    break;
                case AssetBundleBuildType.ui:
                    BuildList = RootDirByDir(targetPath, getFilter(type));
                    break;
            }
			//格式化输出目录
			outPath = PathTool.FormationPath (outPath);
            //判断是否有ab需要打包
            if (BuildList != null && BuildList.Count > 0)
            {
                //开始打包
                try
                {
                    BuildPipeline.BuildAssetBundles(outPath, BuildList.ToArray(), buildOptions, buildtarget);
                    FileTool.ChangeFileName(outPath + "/" + FileTool.GetDirectoryName(outPath), getMainManifestName(type));
                    FileTool.ChangeFileName(outPath + "/" + FileTool.GetDirectoryName(outPath) + ".manifest", getMainManifestName(type));
                }
                catch (Exception e)
                {
                    Debug.LogError(e.ToString());
                }
            }
            else
            {
                Debug.LogError("没有任何需打包的文件!");
            }
		}

        //打包时 生成的全局依赖关系文件名
        private static string getMainManifestName(AssetBundleBuildType type)
        {
            switch (type)
            {
                case AssetBundleBuildType.ui:
                    return "UIGlobalDependencies";
                case AssetBundleBuildType.effect:
                    return "EffectGlobalDependencies";
                case AssetBundleBuildType.actor:
                    return "ActorGlobalDependencies";
                case AssetBundleBuildType.scene:
                    return "SceneGlobalDependencies";
            }
            return "null_main";
        }

        //根据资源类型获取需要打包哪些后缀的资源
		public static string[] getFilter (AssetBundleBuildType type)
		{
			switch (type) {
			    case AssetBundleBuildType.ui:
				    return new string[]{ ".prefab", ".png", ".jpg", ".mat" };
			    case AssetBundleBuildType.effect:
				    return new string[]{ ".prefab", ".png", ".jpg" };
			    case AssetBundleBuildType.actor:
				    return new string[]{ ".prefab" };
                case AssetBundleBuildType.scene:
                    return new string[] {".unity" };
			}
			return new string[]{ ".prefab", ".png", ".jpg", ".mat" };
		}

        //======================================当前项目中用到的打包策略(每种类型的资源分布不同分开写更清晰)==========================================

        /// <summary>
        /// 一级目录以文件为单位
        /// </summary>
        /// <param name="sceneRootPath"></param>
        /// <param name="filters"></param>
        /// <returns></returns>
        private static List<AssetBundleBuild> RootDirByFile(string targetPath, string[] filters)
        {
            return GetAssetBundleBuild(targetPath,filters,true);
        }

        /// <summary>
        /// 一级目录以目录为单位
        /// </summary>
        /// <param name="sceneRootPath"></param>
        /// <param name="filters"></param>
        /// <returns></returns>
        private static List<AssetBundleBuild> RootDirByDir(string targetPath, string[] filters)
        {
            return GetAssetBundleBuild(targetPath, filters, false);
        }

        /// <summary>
        /// 二级目录以文件为单位
        /// </summary>
        /// <param name="sceneRootPath"></param>
        /// <param name="filters"></param>
        /// <returns></returns>
        private static List<AssetBundleBuild> SecondDirByFile(string targetPath,string[] filters)
        {
            targetPath = PathTool.FormationPath(targetPath);
            List<AssetBundleBuild> result = new List<AssetBundleBuild>();
            if (!Directory.Exists(targetPath))
            {
                Debug.LogError("打包目录打不到 目录:" + targetPath);
                return result;
            }
            string[] dirList = Directory.GetDirectories(targetPath);
            foreach(string dir in dirList){
                result.AddRange(GetAssetBundleBuild(dir,filters,true));
            }
            return result;
        }

        /// <summary>
        /// 二级目录以目录为单位
        /// </summary>
        /// <param name="sceneRootPath"></param>
        /// <param name="filters"></param>
        /// <returns></returns>
        private static List<AssetBundleBuild> SecondDirByDir(string targetPath, string[] filters)
        {
            targetPath = PathTool.FormationPath(targetPath);
            List<AssetBundleBuild> result = new List<AssetBundleBuild>();
            if (!Directory.Exists(targetPath))
            {
                Debug.LogError("打包目录打不到 目录:" + targetPath);
                return result;
            }
            string[] dirList = Directory.GetDirectories(targetPath);
            foreach (string dir in dirList)
            {
                result.AddRange(GetAssetBundleBuild(dir,filters,false));
            }
            return result;
        }

        /// <summary>
        /// 目标目录，符合的后缀，是否以文件行式
        /// </summary>
        /// <param name="Dir"></param>
        /// <param name="filters"></param>
        /// <param name="isFile"></param>
        /// <returns></returns>
        private static List<AssetBundleBuild> GetAssetBundleBuild(string Dir,string[] filters,bool isFile)
        {
            List<AssetBundleBuild> result = new List<AssetBundleBuild>();

            if(!Directory.Exists(Dir))
            {
                Debug.LogError("找不到目录:" + Dir);
                return result;
            }
            //以文件为单位
            if (isFile)
            {
                string[] fileList = Directory.GetFiles(Dir);
                foreach (string f in fileList)
                {
                    string filePath = f;
                    //格式化该文件路径
                    filePath = PathTool.FormationPath(filePath);
                    //如果后缀符合
                    if (ContaisExt(filePath, filters))
                    {
                        AssetBundleBuild ab = new AssetBundleBuild();
                        ab.assetBundleName = FormatBundleName(filePath);
                        ab.assetNames = new string[1];
                        filePath = PathTool.RemoveTo(filePath, PathTool.AssetsFlag);
                        ab.assetNames.SetValue(filePath, 0);
                        result.Add(ab);
                    }
                }
            }
            //以目录为单位
            else
            {
                string[] directoryList = Directory.GetDirectories(Dir);
                foreach (string dp in directoryList)
                {
                    string directoryPath = dp;
                    directoryPath = PathTool.FormationPath(directoryPath);
                    string[] fileList = Directory.GetFiles(directoryPath);
                    AssetBundleBuild ab = new AssetBundleBuild();
                    ab.assetBundleName = FormatBundleName(directoryPath);
                    List<string> assetNameList = new List<string>();
                    foreach (string f in fileList)
                    {
                        string filePath = f;
                        filePath = PathTool.FormationPath(filePath);
                        if (ContaisExt(filePath, filters))
                        {
                            filePath = PathTool.RemoveTo(filePath, PathTool.AssetsFlag);
                            assetNameList.Add(filePath);
                        }
                    }
                    ab.assetNames = assetNameList.ToArray();
                    result.Add(ab);
                }
            }
            return result;
        }

        //=====================================================end================================================

		//根据文件目录 拿到assetbundlename
		private static string FormatBundleName (string targetPath)
		{
			string assetBundleName = targetPath;
			//去掉后缀
			int dotIndex = assetBundleName.LastIndexOf (".");
			if (dotIndex > -1)
				assetBundleName = assetBundleName.Remove (dotIndex);
			//去掉以 assetbundleStr为索引的之前的路径
			assetBundleName = PathTool.RemoveTo(assetBundleName,PathTool.AssetBundleFlag);
			return assetBundleName;
		}

		//后缀名是否符合
		private static bool ContaisExt (string filePath, string[] filters)
		{
            string ext = Path.GetExtension(filePath);
			foreach (string extItem in filters) {
				if (ext.ToLower () == extItem.ToLower ())
					return true;
			}
			return false;
		}

	}
}

